home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / info.txt < prev    next >
Text File  |  1999-05-23  |  13KB  |  487 lines

  1. Description of the -listinfo output.
  2. ------------------------------------
  3.  
  4. Grammar:
  5. --------
  6.     start -> ENTRY*
  7.     ENTRY -> ENTRYNAME ENTRYVALUE
  8.     ENTRYNAME -> SYMBOL
  9.     ENTRYVALUE -> SYMBOL | STRING | ENTRYLIST
  10.     ENTRYLIST -> '(' ENTRY* ')'
  11.     SYMBOL -> any char except separator, '"', '(', ')'
  12.     STRING -> default C string in double quote ""
  13.  
  14. Any space (specifically any char which C function ispace() tells is a
  15. space) is considered a separator and must be ignored.
  16.  
  17.  
  18. Semantic:
  19. ---------
  20. game (...)
  21. Definition of all games emulated.
  22.  
  23. resource (...)
  24. Definition of a resource. Actually the only two resource are
  25. the NeoGeo BIOS roms (named 'neogeo') and the YM-3812 samples
  26. (named 'ym3812').
  27.  
  28.  
  29. Entries common for 'game' and 'resource'
  30. ----------------------------------------
  31. name NAME
  32. Name of the game or resource. This is the only required item.
  33. The specified NAME is unique in all file.
  34.  
  35. description DESCRIPTION
  36. Generic description.
  37.  
  38. manufacturer MANUFACTURER
  39. Manufacturer of the game or resource.
  40.  
  41. year YEAR
  42. Year of the game or resource.
  43.  
  44. romof NAME
  45. The game or resource use rom of another game or resource named NAME.
  46. [Equal to cloneof entry in GameDriver specification.]
  47.  
  48. sampleof NAME
  49. The game or resource use sample of another game or resource named NAME.
  50. [Is the first element with starting * in the samplenames array.]
  51.  
  52. rom '(' name NAME size SIZE crc CRC ')'
  53. Rom specification his name, size and crc.
  54.  
  55. sample NAME
  56. Sample specification.
  57.  
  58.  
  59. Entries specific for 'game'
  60. -------------------------
  61. cloneof NAME
  62. Clone-of relathionship. This is intended to express an abstract
  63. clone-of relathionship.    [It's equal to the cloneof entry in gamedriver
  64. specification with the exception of the neogeo game which is not reported
  65. has a parent of any game.]
  66.  
  67. chip '(' type (cpu | audio) [flags audio] name NAME [clock CLOCK] ')'
  68. List of hardware chips which the game use.
  69. [A MAME cpu used for sound has "flags audio"]
  70.  
  71. video '(' (screen raster | vector) [x X y Y] colors NCOLORS freq NFREQ ')'
  72. Many information of the game video hardware.
  73.  
  74. input '(' players NPLAYERS [control TYPE] [buttons NBUTTONS] coins NCOINS ')'
  75. Many information of the game input hardware.
  76.  
  77. driver '(' status (preliminary | good) color (preliminary | imperfect | good)
  78.   hiscore (preliminary | good) colordeep NCOLORBITS credits CREDITS ')'
  79. Many information of the MAME driver status and requirements.
  80.  
  81. sound (channels NUMBER)
  82. Number of the sound channels.
  83.  
  84.  
  85. How to read the file
  86. --------------------
  87. If you have the necessity to read the output of -listinfo option
  88. you must do attention of these issues:
  89.  
  90. 1) You can't do any assumption of space indentation.
  91. 2) You can't do any assumption of max line length. All output can be
  92.    in a very long line.
  93. 3) You can't do any assumption of order of the entries.
  94. 4) You can't do any assumption of the presence of any entry except the
  95.    game.name and resource.name which are mandatory and unique.
  96. 5) You must skip entry unknow.
  97. 6) Spaces are required only for separing SYMBOL.
  98. 7) Lists of entry empty are valid.
  99.  
  100. For example:
  101.  
  102.     game(description"Pac Man (Midway)"unknowentry()name pacman rom(size 4096 name pacman.6e crc c1e6ab10))
  103.  
  104. is a valid output.
  105.  
  106. Example
  107. -------
  108. This is a complete module for reading info files.
  109.  
  110. info.h Library header
  111. info.c Library module
  112. test.c Example of use
  113.  
  114. -- info.h --------------------------------------------------------------------
  115. #ifndef __INFO_H
  116. #define __INFO_H
  117.  
  118. #ifdef __cplusplus
  119. extern "C" {
  120. #endif
  121.  
  122. #include <stdio.h>
  123.  
  124. enum info_t {
  125.     info_error,      /* Generic error in reading */
  126.     info_eof,     /* End of file got at valid position */
  127.     info_symbol,     /* Symbol */
  128.     info_open,     /* ( */
  129.     info_close,     /* ) */
  130.     info_string      /* C string (automatically converted) */
  131. };
  132.  
  133. void info_init(void);
  134. void info_done(void);
  135. const char* info_text_get(void);
  136. enum info_t info_token_get(FILE* f);
  137. enum info_t info_skip_value(FILE* f);
  138. unsigned info_row_get(void);
  139. unsigned info_col_get(void);
  140. unsigned info_pos_get(void);
  141.  
  142. #ifdef __cplusplus
  143. }
  144. #endif
  145.  
  146. #endif
  147. ------------------------------------------------------------------------------
  148.  
  149. -- info.c --------------------------------------------------------------------
  150. #include "info.h"
  151.  
  152. #include <ctype.h>
  153. #include <string.h>
  154. #include <malloc.h>
  155. #include <assert.h>
  156.  
  157. /* Start size of buffer */
  158. #define INFO_BUF_MIN 64
  159.  
  160. /* Buffer used for storing last token */
  161. static unsigned info_buf_mac = 0;
  162. static unsigned info_buf_max = 0;
  163. static char* info_buf_map = 0;
  164.  
  165. /* Position in the stream */
  166. static unsigned info_pos = 0; /* Char */
  167. static unsigned info_row = 0; /* Row */
  168. static unsigned info_col = 0; /* Column */
  169.  
  170. /* Inizialize the info reading system */
  171. void info_init(void) {
  172.     info_buf_max = 0;
  173.     info_buf_map = 0;
  174.     info_pos = 0;
  175.     info_row = 0;
  176.     info_col = 0;
  177. }
  178.  
  179. /* Deinizialize the info reading system */
  180. void info_done(void) {
  181.     free(info_buf_map);
  182. }
  183.  
  184. /* Get information of file position */
  185. unsigned info_row_get(void) {
  186.     return info_row;
  187. }
  188.  
  189. unsigned info_col_get(void) {
  190.     return info_col;
  191. }
  192.  
  193. unsigned info_pos_get(void) {
  194.     return info_pos;
  195. }
  196.  
  197. /* Resize the buffer */
  198. static void info_buf_resize(unsigned size) {
  199.     if (!info_buf_max)
  200.         info_buf_max = INFO_BUF_MIN;
  201.     else
  202.         info_buf_max *= 2;
  203.     if (size > info_buf_max)
  204.         info_buf_max = size;
  205.     info_buf_map = realloc(info_buf_map, info_buf_max );
  206.     assert(    info_buf_map );
  207. }
  208.  
  209. /* Add a char to the buffer end */
  210. static inline void info_buf_add(char c) {
  211.     if (info_buf_mac >= info_buf_max)
  212.         info_buf_resize(info_buf_mac + 1);
  213.     info_buf_map[info_buf_mac++] = c;
  214. }
  215.  
  216. /* Reset the buffer */
  217. static void info_buf_reset() {
  218.     info_buf_mac = 0;
  219. }
  220.  
  221. /* Return last token text if is a info_symbol or a info_string token */
  222. const char* info_text_get(void) {
  223.     /* ensure the buffer end with zero */
  224.     if (info_buf_mac==0 || info_buf_map[info_buf_mac-1]!=0)
  225.         info_buf_add(0);
  226.     return info_buf_map;
  227. }
  228.  
  229. /* Read a char from file */
  230. static int info_getc(FILE* f) {
  231.     int c =    fgetc(f);
  232.     switch (c) {
  233.         case EOF:
  234.             break;
  235.         case '\n':
  236.             info_col = 0;
  237.             ++info_row;
  238.             ++info_pos;
  239.             break;
  240.         default:
  241.             ++info_col;
  242.             ++info_pos;
  243.             break;
  244.     }
  245.     return c;
  246. }
  247.  
  248. /* Unget a char from file */
  249. static void info_ungetc(int c, FILE* f) {
  250.     --info_pos;
  251.     --info_col;
  252.     ungetc(c,f);
  253. }
  254.  
  255. static enum info_t get_symbol(FILE* f,int c) {
  256.     while (c!=EOF && !isspace(c) && c!='(' && c!=')' && c!='\"') {
  257.         info_buf_add(c);
  258.         c = info_getc(f);
  259.     }
  260.     /* no reason to unget space or EOF */
  261.     if (c!=EOF && !isspace(c))
  262.         info_ungetc(c,f);
  263.     return info_symbol;
  264. }
  265.  
  266. static unsigned hexdigit(char c) {
  267.     if (isdigit(c))
  268.         return c - '0';
  269.     return toupper(c) - 'A' + 10;
  270. }
  271.  
  272. static enum info_t get_string(FILE* f) {
  273.     int c = info_getc(f);
  274.     while (c!=EOF && c!='\"') {
  275.         if (c=='\\') {
  276.             c = info_getc(f);
  277.             switch (c) {
  278.                 case 'a' : info_buf_add('\a'); break;
  279.                 case 'b' : info_buf_add('\b'); break;
  280.                 case 'f' : info_buf_add('\f'); break;
  281.                 case 'n' : info_buf_add('\n'); break;
  282.                 case 'r' : info_buf_add('\r'); break;
  283.                 case 't' : info_buf_add('\t'); break;
  284.                 case 'v' : info_buf_add('\v'); break;
  285.                 case '\\' : info_buf_add('\\'); break;
  286.                 case '?' : info_buf_add('\?'); break;
  287.                 case '\'' : info_buf_add('\''); break;
  288.                 case '\"' : info_buf_add('\"'); break;
  289.                 case 'x' : {
  290.                     int d0,d1;
  291.                     unsigned char cc;
  292.                     d0 = info_getc(f);
  293.                     if (!isxdigit(d0))
  294.                         return info_error;
  295.                     d1 = info_getc(f);
  296.                     if (!isxdigit(d1))
  297.                         return info_error;
  298.                     cc = hexdigit(d0) * 16 + hexdigit(d1);
  299.                     info_buf_add(cc);
  300.                 }
  301.                 break;
  302.                 default:
  303.                     info_buf_add('\\');
  304.                     info_buf_add(c);
  305.                 break;
  306.             }
  307.         } else {
  308.             info_buf_add(c);
  309.         }
  310.         c = info_getc(f);
  311.     }
  312.     if (c!='\"')
  313.         return info_error;
  314.     return info_string;
  315. }
  316.  
  317. /* Extract a token */
  318. enum info_t info_token_get(FILE* f) {
  319.     int c = info_getc(f);
  320.     /* reset the buffer */
  321.     info_buf_reset();
  322.     /* skip space */
  323.     while (c!=EOF && isspace(c)) {
  324.         c = info_getc(f);
  325.     }
  326.     /* get token */
  327.     switch (c) {
  328.         case EOF:
  329.             return info_eof;
  330.         case '(':
  331.             return info_open;
  332.         case ')':
  333.             return info_close;
  334.         case '\"':
  335.             return get_string(f);
  336.         default:
  337.             return get_symbol(f,c);
  338.     }
  339. }
  340.  
  341. /* Skip a value token
  342.  * note:
  343.  *   Skip recusively any info_open and info_close
  344.  * return:
  345.  *   info_error error
  346.  *   otherwise last token skipped
  347.  */
  348. enum info_t info_skip_value(FILE* f) {
  349.     /* read value token */
  350.     enum info_t t = info_token_get(f);
  351.     switch (t) {
  352.         case info_open:
  353.             t = info_token_get(f);
  354.             if (t==info_error)
  355.                 return info_error;
  356.             while (t!=info_close) {
  357.                 /* first read type as a symbol */
  358.                 if (t!=info_symbol)
  359.                     return info_error;
  360.                 /* second skip the value */
  361.                 t = info_skip_value(f);
  362.                 /* two value required */
  363.                 if (t==info_error)
  364.                     return info_error;
  365.                 /* read next token, a type or a info_close */
  366.                 t = info_token_get(f);
  367.                 if (t==info_error)
  368.                     return info_error;
  369.             }
  370.         break;
  371.         case info_symbol:
  372.         case info_string:
  373.         break;
  374.         default:
  375.             return info_error;
  376.     }
  377.     return t;
  378. }
  379. ------------------------------------------------------------------------------
  380.  
  381. -- test.c --------------------------------------------------------------------
  382. #include "info.h"
  383.  
  384. #include <stdio.h>
  385. #include <stdlib.h>
  386.  
  387. #define true 1
  388. #define false 0
  389.  
  390. int info_load(FILE* f) {
  391.     enum info_t token = info_token_get(f);
  392.     while (token!=info_eof) {
  393.         if (token != info_symbol) return false;
  394.         if (strcmp(info_text_get(),"game")==0) {
  395.             if (info_token_get(f) != info_open) return false;
  396.             token =    info_token_get(f);
  397.             while (token != info_close) {
  398.                 if (token != info_symbol)
  399.                     return false;
  400.                 if (strcmp(info_text_get(),"name")==0) {
  401.                     if (info_token_get(f) != info_symbol) return false;
  402.                     printf("name %s\n", info_text_get() );
  403.                 } else if (strcmp(info_text_get(),"description")==0) {
  404.                     if (info_token_get(f) != info_string) return false;
  405.                     printf("description %s\n", info_text_get() );
  406.                 } else if (strcmp(info_text_get(),"manufacturer")==0) {
  407.                     if (info_token_get(f) != info_string) return false;
  408.                     printf("manufacturer %s\n", info_text_get() );
  409.                 } else if (strcmp(info_text_get(),"year")==0) {
  410.                     if (info_token_get(f) != info_symbol) return false;
  411.                     printf("year %s\n", info_text_get() );
  412.                 } else if (strcmp(info_text_get(),"cloneof")==0) {
  413.                     if (info_token_get(f) != info_symbol) return false;
  414.                     printf("cloneof %s\n", info_text_get() );
  415.                 } else if (strcmp(info_text_get(),"romof")==0) {
  416.                     if (info_token_get(f) != info_symbol) return false;
  417.                     printf("romof %s\n", info_text_get() );
  418.                 } else if (strcmp(info_text_get(),"sampleof")==0) {
  419.                     if (info_token_get(f) != info_symbol) return false;
  420.                     printf("sampleof %s\n", info_text_get() );
  421.                 } else if (strcmp(info_text_get(),"rom")==0) {
  422.                     if (info_token_get(f) != info_open)  return false;
  423.                     token =    info_token_get(f);
  424.                     while (token != info_close) {
  425.                         if (token != info_symbol) return false;
  426.                         if (strcmp(info_text_get(),"name")==0) {
  427.                             if (info_token_get(f) != info_symbol) return false;
  428.                             printf("romname %s\n", info_text_get() );
  429.                         } else if (strcmp(info_text_get(),"size")==0) {
  430.                             if (info_token_get(f) != info_symbol) return false;
  431.                             printf("romsize %s\n", info_text_get() );
  432.                         } else if (strcmp(info_text_get(),"crc")==0) {
  433.                             if (info_token_get(f) != info_symbol) return false;
  434.                             printf("romcrc %s\n", info_text_get() );
  435.                         } else {
  436.                             if (info_skip_value(f) == info_error) return false;
  437.                         }
  438.                         token = info_token_get(f);
  439.                     }
  440.                 } else if (strcmp(info_text_get(),"driver")==0) {
  441.                     if (info_token_get(f) != info_open)  return false;
  442.                     token =    info_token_get(f);
  443.                     while (token != info_close) {
  444.                         if (token != info_symbol) return false;
  445.                         if (strcmp(info_text_get(),"status")==0) {
  446.                             if (info_token_get(f) != info_symbol) return false;
  447.                             printf("driverstatus %s\n", info_text_get() );
  448.                         } else {
  449.                             if (info_skip_value(f) == info_error) return false;
  450.                         }
  451.                         token = info_token_get(f);
  452.                     }
  453.                 } else if (strcmp(info_text_get(),"sample")==0) {
  454.                     if (info_token_get(f) != info_symbol) return false;
  455.                     printf("samplenames %s\n", info_text_get() );
  456.                 } else {
  457.                     if (info_skip_value(f) == info_error) return false;
  458.                 }
  459.                 token = info_token_get(f);
  460.             }
  461.         } else {
  462.             if (info_skip_value(f) == info_error) return false;
  463.         }
  464.         token = info_token_get(f);
  465.     }
  466.  
  467.     return true;
  468. }
  469.  
  470. int main() {
  471.     info_init();
  472.  
  473.     if (!info_load(stdin)) {
  474.         info_done();
  475.         fprintf(stderr,"Error reading at row %d column %d\n",info_row_get()+1,info_col_get()+1);
  476.         exit(EXIT_FAILURE);
  477.     }
  478.  
  479.     info_done();
  480.  
  481.     return EXIT_SUCCESS;
  482. }
  483. ------------------------------------------------------------------------------
  484.  
  485.  
  486.  
  487.